﻿using System;
using System.Windows;
using System.Windows.Media;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
using System.Linq;
using JustinAngel.Neurons.Framework;

namespace JustinAngel.Neurons.Services
{
    public class ImageServiceState
    {
        public Action<ImageSource, object> Action;
        public object State;
    }

    public class ImageService : IImageService
    {
   static Dictionary<string, ImageSource> images = new Dictionary<string, ImageSource>();
        static Dictionary<string, List<ImageServiceState>> requestQueue = new Dictionary<string, List<ImageServiceState>>();
        static int maxSize = 20;
        static private object mutex = new object();

        [Dependency]
        public IWebRequestMaker WebRequestMaker { get; set; }

        public ImageService()
        {
            IoC.BuildUp(this);
        }

        public void GetImageData(string url, string key, Action<ImageSource, object> action, object state)
        {
            key =  key;
            lock (mutex)
            {
                if (images.ContainsKey(key))
                {
                    action(images[key], state);
                    return;
                }

                if (requestQueue.ContainsKey(key))
                {
                    requestQueue[key].Add(new ImageServiceState()
                    {
                        Action = action,
                        State = state
                    });
                    return;
                }

                requestQueue.Add(key, new List<ImageServiceState>() 
                    {
                        new ImageServiceState()
                        {
                            Action = action,
                            State = state
                        }
                    }
                    );
            }
            WebRequestMaker.Start2(url, (stream, ex, asyncState) =>
            {
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    BitmapImage img = null;
                    if (stream != null)
                    {
                        try
                        {
                            img = new BitmapImage();
                            img.CreateOptions = BitmapCreateOptions.None;
                            img.SetSource(stream);
                            // since cover art probably won't be requested multiple times we won't cache it
                            images.Add(key, img);
                        }
                        catch
                        {
                            img = null;
                        }
                    }

                    lock (mutex)
                    {
                        if (images.Count > maxSize)
                        {
                            images.Remove(images.Keys.First());
                        }
                        if (requestQueue.ContainsKey(key))
                        {
                            foreach (var request in requestQueue[key])
                            {
                                request.Action(img, request.State);
                            }
                            requestQueue.Remove(key);
                        }
                    }
                });
            }, state);
        }
    }
}
